package com.golxen.framework.event;


import com.golxen.utils.LogUtil;

import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

//事件源：管理事件监听器
public class BaseMultiEventSource implements IEventSource {

	// SourceObject
	private HashMap<Integer, Collection<IEventListener>> eventSourceHashMap;
	//防止移除监听器与注册监听器和触发事件同时执行，产生数据不一致的情况。读写不可同时，且只能有一个写线程。
	private ReadWriteLock lock;

	public BaseMultiEventSource() {
		eventSourceHashMap = new HashMap<>();
		lock = new ReentrantReadWriteLock(false);
	}

	@Override
	public void addListener(int eEvent, IEventListener listener) {
		lock.writeLock().lock();

		Collection<IEventListener> listListeners = eventSourceHashMap.get(eEvent);
		if (listListeners == null) {
			// 创建线程安全版集合
			listListeners = Collections.synchronizedSet(new HashSet<>());
			eventSourceHashMap.put(eEvent, listListeners);
		}

		if (!listListeners.contains(listener)) {
			listListeners.add(listener);
		}

		lock.writeLock().unlock();
	}

	@Override
	public void removeListener(int eEvent, IEventListener listener) {
		lock.writeLock().lock();

		Collection<IEventListener> listListeners = eventSourceHashMap.get(eEvent);
		if (listListeners != null && listListeners.contains(listener)) {
			listListeners.remove(listener);
		}

		lock.writeLock().unlock();
	}

	@Override
	public boolean notifyListener(int eEvent, BaseEventArg eventArg) {
		lock.readLock().lock();

		List<IEventListener> tEventListeners = eventSourceHashMap.get(eEvent) == null ? null
				: new ArrayList<>(eventSourceHashMap.get(eEvent));

		lock.readLock().unlock();

		if (tEventListeners != null) {
			for (IEventListener iEventListener : tEventListeners) {
				try {
					iEventListener.onEvent(eventArg);
				} catch (Exception ex) {
					LogUtil.COMMON.error("The class :" + iEventListener.getClass(), ex);
				}
			}
			return true;
		}
		return false;
	}

}
